package org.jeecg.modules.system.util;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.modules.shiro.authc.config.DynamicDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @author sakur
 * @since 2022/11/14
 */
@Configuration
public class SakurUtils {

    @Value("${spring.datasource.MySQL-url}")
    public String MySQL_url;

    @Value("${spring.datasource.dynamic.datasource.master.url}")
    public String main_url;

    @Value("${spring.datasource.dynamic.datasource.master.username}")
    public String main_username;

    @Value("${spring.datasource.dynamic.datasource.master.password}")
    public String main_password;

    @Value("${spring.datasource.dynamic.datasource.multi-datasource.url}")
    public String url;

    @Value("${spring.datasource.dynamic.datasource.multi-datasource.username}")
    public String username;

    @Value("${spring.datasource.dynamic.datasource.multi-datasource.password}")
    public String password;

    @Value("${spring.datasource.dynamic.datasource.multi-datasource.driver-class-name}")
    public String driverClassName;

    @Value("${spring.datasource.dynamic.druid.initial-size}")
    public int initialSize;

    @Value("${spring.datasource.dynamic.druid.min-idle}")
    public int minIdle;

    @Value("${spring.datasource.dynamic.druid.maxActive}")
    public int maxActive;

    @Value("${spring.datasource.dynamic.druid.maxWait}")
    public int maxWait;

    @Value("${spring.datasource.dynamic.druid.timeBetweenEvictionRunsMillis}")
    public int timeBetweenEvictionRunsMillis;

    @Value("${spring.datasource.dynamic.druid.minEvictableIdleTimeMillis}")
    public int minEvictableIdleTimeMillis;

    @Value("${spring.datasource.dynamic.druid.testWhileIdle}")
    public boolean testWhileIdle;

    @Value("${spring.datasource.dynamic.druid.testOnBorrow}")
    public boolean testOnBorrow;

    @Value("${spring.datasource.dynamic.druid.testOnReturn}")
    public boolean testOnReturn;

    @Value("${spring.datasource.dynamic.druid.poolPreparedStatements}")
    public boolean poolPreparedStatements;

    @Value("${spring.datasource.dynamic.druid.maxPoolPreparedStatementPerConnectionSize}")
    public int maxPoolPreparedStatementPerConnectionSize;

    /**
     * 获取tenant_datasource连接
     * @return SQL执行statement
     */
    @Bean("TenantDatabaseConnection")
    public Statement TenantDatabaseConnection() {
        try {
            Class.forName(driverClassName);
            Connection c = DriverManager.getConnection(url, username, password);
            return c.createStatement();
        } catch (ClassNotFoundException e) {
            System.out.println("SakurUtils Class.forName() error");
        } catch (SQLException e) {
            System.out.println("SakurUtils getConnection() error");
        }
        return null;
    }

    /**
     * 初始化动态数据源
     * 将主数据库放入连接池
     */
    @Bean("dynamicDataSource")
    public DataSource dynamicDataSource() {
        Map<Object, Object> map = new HashMap<>(1);
        DruidDataSource dataSource = new DruidDataSource();
        try {
            dataSource.setDriverClassName(driverClassName);
            dataSource.setUrl(main_url);
            dataSource.setUsername(main_username);
            dataSource.setPassword(main_password);
            // 测试连接
            dataSource.getConnection().close();
            map.put("master", dataSource);
        } catch (Exception e) {
            throw new IllegalStateException("[master]：数据源连接不上， 可能是连接参数有误！");
        }
        return new DynamicDataSource(dataSource, map);
    }

    /**
     * ResultSet to JSONArray
     */
    public static JSONArray extractJSONArray(ResultSet rs) throws SQLException {
        ResultSetMetaData md = rs.getMetaData();
        int num = md.getColumnCount();
        JSONArray array = new JSONArray();
        while (rs.next()) {
            JSONObject mapOfColValues = new JSONObject();
            for (int i = 1; i <= num; i++) {
                mapOfColValues.put(md.getColumnName(i), rs.getObject(i));
            }
            array.add(mapOfColValues);
        }
        return array;
    }
}
